from flask import request
from flask_restx import fields, Resource
from flask_jwt_extended import jwt_required, get_jwt_identity
from .. import db
from ..models import Article, ArticleVisibility, User
from . import make_namespace
from ..core import make_response, make_paginated
from flask import current_app


api = make_namespace("03.Articles", "文章模块")


article_in_model = api.model("ArticleIn", {
	"title": fields.String(required=True),
	"content": fields.String(required=True),
	"visibility": fields.String(enum=[v.value for v in ArticleVisibility], default=ArticleVisibility.public.value),
})

article_out_model = api.model("Article", {
	"id": fields.Integer,
	"title": fields.String,
	"content": fields.String,
	"visibility": fields.String,
	"author_id": fields.Integer,
})


@api.route("")
class ArticleList(Resource):
	def get(self):
		# Public can list only public articles
		page_num = int(request.args.get("page", 1))
		page_size = int(request.args.get("page_size", current_app.config.get("PAGE_SIZE", 20)))
		q = Article.query.filter_by(visibility=ArticleVisibility.public).order_by(Article.id.desc())
		total = q.count()
		items = [a.to_dict() for a in q.offset((page_num - 1) * page_size).limit(page_size).all()]
		data = make_paginated(items, total, page_num, page_size)
		return make_response(data)

	@jwt_required()
	@api.expect(article_in_model, validate=True)
	def post(self):
		user = User.query.get(int(get_jwt_identity()))
		payload = request.get_json()
		article = Article(
			title=payload["title"],
			content=payload["content"],
			visibility=ArticleVisibility(payload.get("visibility", ArticleVisibility.public.value)),
			author_id=user.id,
		)
		db.session.add(article)
		db.session.commit()
		return make_response(article.to_dict())


@api.route("/mine")
class MyArticles(Resource):
	@jwt_required()
	def get(self):
		user_id = int(get_jwt_identity())
		page_num = int(request.args.get("page", 1))
		page_size = int(request.args.get("page_size", current_app.config.get("PAGE_SIZE", 20)))
		q = Article.query.filter_by(author_id=user_id).order_by(Article.id.desc())
		total = q.count()
		items = [a.to_dict() for a in q.offset((page_num - 1) * page_size).limit(page_size).all()]
		data = make_paginated(items, total, page_num, page_size)
		return make_response(data)


@api.route("/<int:article_id>")
class ArticleDetail(Resource):
	def get(self, article_id: int):
		article = Article.query.get_or_404(article_id)
		if article.visibility == ArticleVisibility.private:
			# Private is hidden from public
			return make_response(code=403, msg="该文章为私有", data=None)
		return make_response(article.to_dict())

	@jwt_required()
	@api.expect(article_in_model, validate=False)
	def put(self, article_id: int):
		user_id = int(get_jwt_identity())
		article = Article.query.get_or_404(article_id)
		if article.author_id != user_id:
			return make_response(code=403, msg="只能修改自己的文章", data=None)
		payload = request.get_json() or {}
		for key in ["title", "content"]:
			if key in payload and payload[key]:
				setattr(article, key, payload[key])
		if "visibility" in payload and payload["visibility"]:
			article.visibility = ArticleVisibility(payload["visibility"])
		db.session.commit()
		return make_response(article.to_dict())

	@jwt_required()
	def delete(self, article_id: int):
		user_id = int(get_jwt_identity())
		article = Article.query.get_or_404(article_id)
		if article.author_id != user_id:
			return make_response(code=403, msg="只能删除自己的文章", data=None)
		db.session.delete(article)
		db.session.commit()
		return make_response({"message": "已删除"})


